Dados e R
Data Wrangling & DataViz

Encontro 2 | 19/08/20024
Henrique Costa | Métodos Estratégicos em FinQuant

Dados e R

Funções

  • Receitas permitem que os chefs preparem guloseimas saborosas
    • As receitas pedem ingredientes
    • Recipes involve one or more steps
    • As etapas transformam os ingredientes em guloseimas
  • Funções são como receitas personalizáveis
    • Funções solicitam entradas (“argumentos”)
    • As funções envolvem uma ou mais linhas de código
    • O código transforma entradas em saídas
    • O uso de funções requer parênteses (geralmente)

doce <- f(ing1, ing2)

Funções - Prática

# CASO DE USO: A função pode executar uma tarefa de forma mais fácil e legível

# MODELO: saída <- nome_da_função(entrada)

9 ^ (1 / 2)

x <- sqrt(9)
x

# ==============================================================================

# LIÇÃO: Também podemos usar funções para transformar objetos

y <- 9

sqrt(y)

# ==============================================================================

# LIÇÃO: Podemos até usar funções para transformar o resultado dos cálculos

2 / 3

round(2 / 3)

# ==============================================================================

# LIÇÃO: Podemos personalizar o que uma função faz usando argumentos

# MODELO: saída <- nome_da_função(argumento, nome_do_argumento = valor_do_argumento)


round(2 / 3, digits = 2)

round(2 / 3, digits = 3)

# ==============================================================================

# LIÇÃO: Alguns argumentos são opcionais porque têm valores padrão

round(2 / 3) # the default value for digits is 0

round(2 / 3, digits = 0)

Vectores

  • Vetores combinam objetos semelhantes em uma coleção
    • Gosto de imaginar um trem puxando vários vagões
    • Um vetor é um objeto com muitos subobjetos
    • Nós nos referimos a cada subobjeto como um elemento
  • Algumas funções transformam cada elemento um de cada vez
    • Dobrar a quantidade de carga em cada vagão
  • Algumas funções resumir em todos os elementos
    • Calcule a carga total em todos os vagões do trem


v <- c(1, 2, 3, 4, 5)

Vetores - Prática

# LIÇÃO: Podemos combinar vários elementos em um vetor

# MODELO: nome_do_vetor <- c(elemento1, elemento2, elemento3)

x <- 4 9 16 25 # error

x <- c(4, 9, 16, 25)
x

y <- c(2, 3)
y

# ==============================================================================

# LIÇÃO: Também podemos combinar vários vetores e elementos

c(x, y)

c(x, y, 20)

# ==============================================================================

# CASO DE USO: Operadores matemáticos transformarão cada elemento individualmente

x + 1

x * 3

x # mas, novamente, isso não será salvo a menos que você use atribuição

# ==============================================================================

# CASO DE USO: Algumas funções também transformarão cada elemento individualmente

sqrt(x)

log(x)

# ==============================================================================

# CASO DE USO: Outras funções resumirão o vetor com um único número

length(x)

sum(x)

mean(x)

Strings

  • Ao programar com R, precisamos de uma maneira de distinguir
    • Nomes de objetos/funções (por exemplo, a função mean)
    • Dados de texto/caractere (por exemplo, a palavra mean)
  • Strings são a maneira do R armazenar dados de texto
    • Strings podem armazenar qualquer caractere (sem regras!)
    • As strings são criadas e exibidas com quotes

::::

Strings

  • R tem ótimas ferramentas para trabalhar com strings
    • As strings podem ser coletadas em vetores
    • Funções especiais podem transformar strings

name <- "John Doe"

:::

Strings - Prática

# CASO DE USO: Strings são a principal maneira de armazenar dados de caracteres em R
 
my_color <- red # error

my_color <- "red" # correto

# ==============================================================================

# CASO DE USO: Strings também podem armazenar símbolos não permitidos em nomes de objetos

dye <- "red#40"
dye

dyes <- c("red#40", "blue#02")
dyes

# ==============================================================================

# ARMADILHA: Muitas operações que você pode fazer com números não funcionarão para strings

dyes + 1 # error

mean(dyes) # error

# ==============================================================================

# CASO DE USO: Mas outras operações funcionam para ambos ou mesmo apenas para strings

length(dyes)

nchar(dyes)

dyes2 <- toupper(dyes)
dyes2

Packages (Pacotes)

  • Livros de receitas são uma ótima maneira de aprender a cozinhar
    • Eles contêm muitas receitas e instruções
    • Navegue em uma livraria online para encontrar um livro de receitas
    • Encomende para adicionar à sua estante pessoal
    • Para usar, retire o livro de receitas da prateleira

Packages (Pacotes)

  • Pacotes são como livros de receitas para R
    • Eles contêm funções e conjuntos de dados úteis
    • Navegue em um repositório online para um pacote
    • Instale para adicioná-lo à sua biblioteca pessoal
    • Para usar, carregue o pacote da biblioteca

library("pkg_name")

Packages - Prática

# CASO DE USO: O pacote stringr adiciona uma função para corrigir a capitalização

students <- c("mary anne", "BENjamin", "Lee")

# ==============================================================================

# ARMADILHA: Mas não podemos usar essa função sem instalar o pacote

str_to_title(students) # error

# ==============================================================================

# LIÇÃO: Instalando um pacote usando RStudio

# - RStudio > Extras pane > Packages tab > Install button

# ==============================================================================

# ARMADILHA: Também precisamos carregar o pacote antes de podermos usá-lo

str_to_title(students) # error

# ==============================================================================

# LIÇÃO: Carregamos o pacote usando library()

library("stringr")
str_to_title(students) # pronto isso funciona!

# ==============================================================================

# LIÇÃO: Também podemos manter nossos pacotes atualizados usando o RStudio

# RStudio > Extras pane > Packages tab > Update button

Wrangle I

Princípio de Dados Tidy (Arrumados)

  • Existem muitas maneiras de armazenar dados
  • Aprenderemos o formato tidy data
    • Os dados devem ser retangulares
    • Cada variável tem sua própria coluna
    • Cada observação tem sua própria linha
    • Cada valor tem sua própria célula

Outros conselhos sobre dados

  • Nomeie todas as variáveis na primeira linha
    • Isso é chamado de linha de cabeçalho
  • Evite células mescladas para armazenamento de dados
    • Estes são bons para comunicação
  • Evite células vazias sempre que possível
    • Marcar dados ausentes como NA
  • Evite formatação como dados para armazenamento
    • por exemplo, codificação de cores não redundante

Arrumando (Tidying) exemplo 1

Não Arrumado (Tidy)

Nome Ann Bob Cat Dom
Idade 13 10 11 11
Peso 56.4 46.8 41.3 43.3

❌ Aqui, cada linha é uma variável e cada coluna é uma observação.

Arrumado (Tidy)

Nome Idade Peso
Ann 13 56.4
Bob 10 46.8
Cat 11 41.3
Dom 11 43.3

✔️ Aqui, cada coluna é uma variável e cada linha é uma observação.

Arrumando (Tidying) exemplo 2

Não arrumado (Tidy)

Nome: Ann Bob Cat Dom
Idade Peso
13 56.4
10 46.8
11 41.3
11 43.3

❌ Aqui, temos dados que não são retangulares porque a variável Names tem sua própria linha.

Arrumado (Tidy)

Nome Idade Peso
Ann 13 56.4
Bob 10 46.8
Cat 11 41.3
Dom 11 43.3

✔️ Aqui, tornamos os dados retangulares movendo a variável Nomes para sua própria coluna.

Arrumando (Tidying) exemplo 3

Não arrumado (Tidy)

country year cases / population
Afghanistan 1999 NA / 19987071
2000 2666 / 20595360
Brazil 1999 37737 / 172006362
2000 80488 / 174504898
China 1999 212258 / 1272915272
2000 213766 / 1280428583

❌ Aqui, mesclamos células e dois valores armazenados em uma única célula.

Arrumado (Tidy)

country year cases population
Afghanistan 1999 NA 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

✔️Aqui, desfazemos a mesclagem dos países e separamos as variáveis de casos e populações em colunas.

Arrumando (Tidying) exemplo 4

Não arrumado

student grade
Amber 91.5 A-
Bristol 86.2 B
Charlene 94.0 A
Diego 89.3 B+
Legend: Psych. Major, Psych. Minor

❌ Aqui, temos um nome de variável ausente e formatação como dados.

Arrumado

student psych grade letter
Amber major 91.5 A-
Bristol minor 86.2 B
Charlene major 94.0 A
Diego NA 89.3 B+

✔️ Aqui, adicionamos uma coluna para a variável psych, removemos a legenda e nomeamos a variável letter.

Arrumando (Tidying) exemplo 5

Não arrumado

student grade letter
Amber 91.5 A-
Bristol* 94.2 A
Class Summary
As 2 Yay!
Bs 0
*Grade was revised.

❌ Aqui, temos dois tipos de dados em um arquivo e uma nota de rodapé como dados.

Arrumado

student grade letter revised
Amber 91.5 A- FALSE
Bristol 94.2 A TRUE
letter count notes
A 2 Yay!
B 0

✔️ Aqui, dividimos os dados em duas tabelas separadas e adicionamos as variáveis revisadas e notas.

Tabelas (Tibbles)

  • R funciona particularmente bem com dados organizados
  • Armazenamos dados organizados em data frames ou tibbles
    • Tibbles são apenas tabelas mais sofisticadas
      (ou seja, eles têm alguns recursos extras)
  • Para usar tibbles, precisamos do pacote tidyverse
  • Tibbles são construídos a partir de um ou mais vetores
    • Os vetores devem ter o mesmo comprimento
    • Eles podem conter diferentes tipos de dados

Vetores

Começamos com três objetos vetoriais separados que têm todos o mesmo comprimento.

Nós configuramos para que o \(n\)-ésimo vagão em cada trem corresponda à mesma observação.

Tibble

Então combinamos os vetores em um único objeto tibble (ou data frame).

Agora, conforme o tibble se move, as variáveis sempre ficam juntas.

Tibbles - Prática

# CONFIGURAÇÃO: Instale e carregue o pacote tidyverse

# Extras pane > Packages tab > Install

library(tidyverse)

# ==============================================================================

# LIÇÃO: Crie um tibble a partir de vetores

x <- c(10, 20, 30, 40)
x

y <- x * 2 - 4
y

my_tibble <- tibble(x, y)
my_tibble

# ==============================================================================

# CASO DE USO: Você pode misturar diferentes tipos de vetores em um único tibble

first_names <- c("Adam", "Billy", "Caitlyn", "Debra")

age_years <- c(12, 13, 10, NA)

guests <- tibble(first_names, age_years)
guests

# ==============================================================================

# DICA: Para economizar tempo, você também pode criar os vetores na chamada tibble

gradebook <- tibble(
  grade = c(95, 83, 90, 76),
  letter = c("a", "b", "a-", "c")
)
gradebook

# ==============================================================================

# ARMADILHA: Não tente combinar tibbles com comprimentos diferentes

y <- c(1, 2, 3)
x <- c("a", "b")

tibble(y, x) #error

# ==============================================================================

# LIÇÃO: No entanto, a exceção é que R irá "reciclar" um único valor

tibble(y, x = "a")

# ==============================================================================

# LIÇÃO: Você pode "extrair" um vetor de um tibble usando $

mytibble <- tibble(x = c(1, 2, 3, 4, 5), y = "test")

mytibble$x

mytibble$y

# ==============================================================================

# ARMADILHA: Não tente extrair um vetor que não existe

mytibble$z #error

Tabelas longas e largas (long x wide)

Tabelas longas e largas (long x wide)

Importação e Exportação

  • Os dados geralmente são armazenados em arquivos de dados
    • Importar arquivos para R é chamado reading
    • Exportar arquivos de R é chamado writing
  • Um tipo de arquivo de dados conveniente é um CSV
    • Isto significa valores separados por vírgula
    • Um arquivo CSV é fácil de compartilhar com outras pessoas
  • O pacote tidyverse pode ler/escrever CSVs
    • Outros pacotes podem ler/escrever outros tipos (e.g., readxl, haven, rio, googlesheets4)

Read/Write - Prática

# CONFIGURAÇÃO: Carregue o pacote tidyverse (se ainda não o fez)

library(tidyverse)

# ==============================================================================

# CASO DE USO: Crie um tibble e grave-o em um arquivo

gradebook <- tibble(
  id = c(123, 456, 789),
  grade = c("A", "B", "A")
)
gradebook

write_csv(gradebook, file = "gradebook.csv")

# NOTA: Você pode ver o novo arquivo no painel Extras > aba Arquivos.
# Você pode abrir o arquivo em outro programa (por exemplo, Microsoft Excel).
# Você também pode enviar este arquivo por e-mail para outra pessoa para compartilhá-lo.

# ==============================================================================

# ARMADILHA: Não troque a ordem do tibble e do file

write_csv("gradebook.csv", gradebook) # error

# ==============================================================================

# CASO DE USO: Ler em um arquivo contendo dados

old_gradebook <- read_csv("gradebook.csv")
old_gradebook

# NOTA: read_csv() examinará e adivinhará o tipo de dado de cada variável.
# Você pode dizer a ele o tipo de dado de cada variável, mas isso é mais avançado.

# ==============================================================================

# ARMADILHA: Não use as funções read.csv() e write.csv()

old_gradebook <- read.csv("gradebook.csv") # not a tibble
old_gradebook

Wrangle II

Vérbos basicos em data wrangling

  • tidyverse fornece ferramentas para controlar tibbles
    • Essas funções são nomeadas após verbos
    • Então, se você nomear seus objetos com base em substantivos
    • …seu código se torna mais fácil de ler
Substantivo(substantivo) ❌ Verbo(substantivo) ✔️
blender(fruit) blend(fruit)
screwdriver(screw) drive(screw)
boxcutter(box) cut(box)

Verbos focados em colunas

  • Selecionar retém apenas certas colunas/variáveis
    • select(TBL, VAR_KEEP, -VAR_DROP)
  • Mutate adiciona ou transforma colunas/variáveis
    • mutate(TBL, NEW_VAR = OLD_VAR / 1000)
  • Rename altera os nomes das colunas/variáveis
    • rename(TBL, NEW_NAME = OLD_NAME)
  • Relocate altera a ordem das colunas/variáveis
    • relocate(TBL, VAR_MOVE, .after = OTHER_VAR)

Select - Prática

# CONFIGURAÇÃO: Carregar pacote e inspecionar exemplo tibble

library(tidyverse) # inclui o pacote dplyr
starwars

# ==============================================================================

# CASO DE USO: Reter apenas as variáveis especificadas

sw <- select(starwars, name)
sw
sw <- select(starwars, name, sex, species)
sw

# ==============================================================================

# ARMADILHA: Não esqueça de salvar a alteração com a atribuição

select(starwars, name, sex, species)
starwars # ainda inclui todas as variáveis

# ==============================================================================

# CASO DE USO: Reter todas as variáveis entre duas variáveis

sw <- select(starwars, name, hair_color:eye_color)
sw

# ==============================================================================

# CASO DE USO: Reter todas as variáveis, exceto as especificadas

sw <- select(starwars, -sex, -species)
sw
sw <- select(starwars, -c(sex, species))
sw
sw <- select(starwars, -c(hair_color:starships))
sw

Mutate - Prática

# CONFIGURAÇÃO: Criar exemplo tibble

patients <- tibble(
  id = c("S1", "S2", "S3"),
  feet = c(6, 5, 5),
  inches = c(1, 7, 2),
  pounds = c(176.3, 124.9, 162.6)
)
patients

# ==============================================================================

# CASO DE USO: Adicionar uma ou mais variáveis

p2 <- mutate(patients, sex = c("M", "F", "F"))
p2

ages <- c(32, 41, 29)
p2 <- mutate(patients, ages = ages)
p2

p2 <- mutate(
  patients, 
  sex = c("M", "F", "F"), 
  ages = ages
)
p2

# ==============================================================================

# CASO DE USO: Calcular variáveis

p2 <- mutate(patients, height = feet + inches / 12)
p2

p2 <- mutate(patients, ln_pounds = log(pounds))
p2

# ==============================================================================

# CASO DE USO: Substituir variáveis

patients <- mutate(patients, height = height / 3.281)
patients

# ==============================================================================

# CASO DE USO: Variáveis duplicadas

p2 <- mutate(patients, weight = pounds)
p2 # tanto peso quanto libras existem

Rename / Relocate - Prática

# CASO DE USO: Alterar o nome de uma ou mais variáveis

starwars

sw <- rename(starwars, Character = name)
sw

sw <- rename(starwars, height_cm = height, mass_kg = mass)
sw

# ==============================================================================

# ARMADILHA: Não troque a ordem e tente old_name = new_name

sw <- rename(starwars, name = Character) # error

# ==============================================================================

# CASO DE USO: Mover variáveis antes ou depois de outra variável

starwars

sw <- relocate(starwars, species, sex, .before = height)
sw

sw <- relocate(starwars, species, sex, .after = name)
sw

# ==============================================================================

# ARMADILHA: Não se esqueça do ponto final!

sw <- relocate(starwars, sex, before = height) 
sw # altura foi renomeada acidentalmente para antes

Verbos focados em linha

  • Arrange classifica as linhas com base em seus valores
    • arrange(TBL, VAR_SORT_UP)
    • arrange(TBL, desc(VAR_SORT_DOWN))
    • arrange(TBL, VAR_SORT_1ST, VAR_SORT_2ND)
  • Filter retém certas linhas com base em critérios
    • filter(TBL, DBL_CRIT > 0)
    • filter(TBL, STR_CRIT == "A")
    • filter(TBL, CRIT1, CRIT2)

Arrange - Prática

# CASO DE USO: Classificar observações por uma variável

starwars

sw <- arrange(starwars, height)
sw # classificado por altura, crescente

sw <- arrange(starwars, name)
sw # classificado por nome, em ordem alfabética

# ==============================================================================

# CASO DE USO: Classificar observações por uma variável, em ordem reversa

sw <- arrange(starwars, desc(height))
sw # classificado por altura, decrescente

sw <- arrange(starwars, desc(name))
sw # classificado por nome, em ordem alfabética reversa

# ==============================================================================

# CASO DE USO: Classificar observações por múltiplas variáveis

sw <- arrange(starwars, hair_color, mass)
sw # classificado por cor do cabelo, então os empates são quebrados por massa

Filter - Prática

# CASO DE USO: Reter apenas observações que atendem a um critério

sw <- filter(starwars, mass > 100)
sw # apenas observações com massa maior que 100

sw <- filter(starwars, mass <= 100)
sw # apenas observações com massa menor ou igual a 100

sw <- filter(starwars, species == "Human")
sw # apenas observações com espécies iguais ao Humano

sw <- filter(starwars, species != "Human")
sw # apenas observações com espécies diferentes do Humano

# ==============================================================================

# ARMADILHA: Não tente usar um único = para testar igualdade

sw <- filter(starwars, height = 150) # error

sw <- filter(starwars, height == 150) # correct
sw 

# ==============================================================================

# ARMADILHA: Não se esqueça de que R diferencia maiúsculas de minúsculas

sw <- filter(starwars, species == "human")
sw # nenhuma observação restante (porque deveria ser Humano)

# ==============================================================================

# CASO DE USO: Reter apenas observações que atendem a critérios complexos

sw <- filter(starwars, mass > 100 & height > 200)
sw # apenas observações com massa acima de 100 E altura acima de 200

sw <- filter(starwars, height < 100 | hair_color == "none")
sw # somente observações com altura menor que 100 OU hair_color igual a nenhum

# ==============================================================================

# ARMADILHA: Não se esqueça de preencher as duas condições

sw <- filter(starwars, mass > 100 & < 200) # error

sw <- filter(starwars, mass > 100 & mass < 200) # correto
sw

# ==============================================================================

# ARMADILHA: Não tente igualar uma string a um vetor

sw <- filter(starwars, species == c("Human", "Droid")) # error

sw <- filter(starwars, species %in% c("Human", "Droid")) # correct
sw

Filter Cheatsheet

Symbol Description Numérico Charactere
< Menor que Sim Não
<= Menor ou igual á Sim Não
> Maior que Sim Não
>= Maior ou igual á Sim Não
== Igual á Sim Sim
!= diferente de Sim Sim
%in% Encontre em Sim Sim
& Lógico - “E” Sim Sim
| Lógico - “Ou” Sim Sim

Wrangle III

Pipes & Pipelines

  • Como podemos fazer operações múltiplas em um objeto?
    1. x <- 10
    2. x2 <- sqrt(x)
    3. x3 <- round(x2)
  • Isso funciona, mas é incômodo e propenso a erros
  • Uma abordagem melhor é usar pipes e pipelines
    • x3 <- 10 %>% sqrt() %>% round()
  • Gosto de ler %>% (ou |>) como “e então…”
    • “Pegue 10 e então sqrt() e então round()”

Pipes - Prática

# CONFIGURAÇÃO: Habilitar o atalho do operador de pipe

# Tools > Global Options... > Code tab > Check "Use Native Pipe Operator"

# Digite |> ou pressione Ctrl+Shift+M (Windows) / Cmd+Shift+M (Mac)

# ==============================================================================

# LIÇÃO: O pipe envia objetos para uma função como seu primeiro argumento

# MODELO: x |> function_name() é o mesmo que function_name(x)

x <- 10

y <- sqrt(x)
y

y <- x |> sqrt()
y

# ==============================================================================

# ARMADILHA: Não se esqueça de remover o objeto da chamada de função

x |> sqrt(x) # wrong

x |> sqrt() # correto

# ==============================================================================

# CASO DE USO: Você ainda pode usar argumentos ao canalizar

z <- round(3.14, digits = 1)
z

z <- 3.14 |> round(digits = 1)
z

# ==============================================================================

# USECASE: Pipes são úteis com tibbles e funções para data wrangling

starwars

sw <- select(starwars, name, species, height)
sw

sw <- starwars |> select(name, species, height)
sw

# ==============================================================================

# ARMADILHA: Não adicione um pipe sem um passo depois dele

sw <- starwars |> select(name, species, height) |> # error

Pipelines - Prática

# CASO DE USO: Você pode encadear vários pipes para criar um pipeline

x <- 10 |> sqrt() |> round()
x

# ==============================================================================

# DICA: Se você quiser ver a saída de um pipeline, você pode canalizar para print()

x <- 10 |> sqrt() |> round() |> print()

# ==============================================================================

# DICA: Para tornar seus pipelines mais legíveis, mova cada etapa para uma nova linha

x <- 
  10 |> 
  sqrt() |> 
  round() |>
  print()

# ==============================================================================

# ARMADILHA: Não coloque o pipe no início de uma linha

x <- 
  10 
  |> sqrt()
  |> round()
  |> print() # error

# ==============================================================================

# CASO DE USO: Encadeie uma série de verbos para controlar dados de forma flexível

tallones <- 
  starwars |> 
  select(name, species, height) |> 
  rename(height_cm = height) |> 
  mutate(height_ft = height_cm / 30.48) |>  
  filter(height_ft > 7) |> 
  arrange(desc(height_ft)) |>  
  print()

Factors

  • Factors são usados para representar dados categóricos
    • Os fatores têm múltiplos [níveis] possíveis{.b .blue}
    • Os níveis são discretos e mutuamente exclusivos
  • Às vezes, as categorias são não ordenadas (nominais)
    • Ação ou Comédia ou Drama
    • Ásia ou Europa ou América do Norte
  • Às vezes, as categorias são ordenadas (ordinal)
    • Suave < Médio < Picante
    • XS < S < M < L < XL

Factors - Prática

# CASO DE USO: Peça a 10 crianças para pedirem 1: nuggets, 2: pizza ou 3: salada

food <- c(2, 2, 1, 2, 1, 2, 1, 1, 2, 2)
food

# ==============================================================================

# LIÇÃO: Podemos transformar esse vetor em um fator com a função factor()

food2 <- factor(food, levels = c(1, 2, 3))
food2

food3 <- factor(food, levels = c(1, 2, 3),
                labels = c("nuggets", "pizza", "salad"))
food3

# ==============================================================================

# CASO DE USO: Também podemos contar cada nível de forma rápida e fácil com a função table()

table(food3)

# ==============================================================================

# ARMADILHA: Não confunda níveis e rótulos (level/label)

food4 <- factor(food, labels = c(1, 2, 3),
                levels = c("nuggets", "pizza", "salad"))
food4 # cheio de <NA> porque não consegue encontrar esses níveis

# ==============================================================================

# CASO DE USO: Você também pode simplesmente inserir strings diretamente (como auto-rótulos)

genre <- c("pop", "metal", "pop", "rock", "rap", "rap", "pop", "rock")
genre

genre2 <- factor(genre) # os níveis observados serão atribuídos em ordem alfabética
genre2

table(genre2)

# ==============================================================================

# LIÇÃO: Se ordinal, insira os níveis de baixo para alto e adicione ordenado = VERDADEIRO

salsa <- c("hot", "mild", "medium", "mild", "medium", "medium")

salsa2 <- factor(salsa, 
                 levels = c("mild", "medium", "hot"), 
                 ordered = TRUE)
salsa2 

# NOTA: Podemos querer visualizar ou modelar fatores ordinais de forma diferente

# ==============================================================================

# CASO DE USO: Trabalhando com fatores em um tibble

cereal <- read_csv("cereal.csv")
cereal

cereal2 <- mutate(cereal, mfr = factor(mfr), type = factor(type))
cereal2

table(cereal2$mfr)

table(cereal2$type)

Valores ausentes

  • Às vezes, seus dados terão valores ausentes
    • Talvez estes nunca tenham sido coletados
    • Talvez os valores tenham sido perdidos/corrompidos
    • Talvez o participante não respondeu
  • Precisamos dizer a R quais valores estão faltando
    • Para fazer isso, definimos esses valores como NA
    • As funções do tidyverse tornam isso fácil
  • A ausência é frequentemente “contagiosa” em R
    por exemplo, um vetor com NA tem uma média desconhecida

Valores ausentes - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse para as funções de leitura e mutação

library(tidyverse)

# ==============================================================================

# ARMADILHA: Códigos numéricos para ausências irão atrapalhar os cálculos em R

heights <- c(149, 158, -999) # aqui usamos -999 para representar um valor ausente

range(heights)

mean(heights)

log(heights) # nosso valor ausente não é mais -999

# ==============================================================================

# CASO DE USO: Use NA para ausência em vez disso

heights2 <- c(149, 158, NA)
heights2

log(heights2) # a NA continuou sendo NA (devido à contagiosidade)

# ==============================================================================

# LIÇÃO: Use na.rm = TRUE para fazer uma função de resumo ignorando os NAs

mean(heights2) # a média é um NA (devido à contagiosidade)

mean(heights2, na.rm = TRUE)

range(heights2, na.rm = TRUE)

# ==============================================================================

# CASO DE USO: Lidando com valores ausentes em tibbles

cereal <- read_csv("cereal.csv")

cereal$rating

range(cereal$rating)

# ==============================================================================

# LIÇÃO: Use na_if() para converter valores específicos para NA durante a modificação

cereal2 <- cereal %>% mutate(rating = na_if(rating, -999))

cereal2$rating

range(cereal2$rating, na.rm = TRUE)

# ==============================================================================

# LIÇÃO: Use read_csv(na) para converter valores específicos para NA durante a leitura

cereal3 <- read_csv("cereal.csv", na = "-999")

cereal3$rating

range(cereal3$rating, na.rm = TRUE)

Wrangle IV

Summarize

  • Embora armazenemos dados sobre muitas observações…
  • …frequentemente queremos resumir observações
    • Isto é como dobrar o tibble para uma linha
  • Vimos funções que resumem vetores
    • length(), sum(), min(), max()
    • mean(), median(), sd(), var()
  • summarize() nos permite usá-los em tibbles
    • Funciona de forma muito semelhante a mutate()
    • Ele sempre cria um tibble como saída

Summarize - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um conjunto de dados de exemplo

library(tidyverse)

sales <- 
  tibble(
    customer = c(1, 2, 3, 1, 3),
    store = c("A", "A", "A", "B", "B"),
    items = c(25, 20, 16, 10, 5),
    spent = c(685, 590, 392, 185, 123)
  ) |> 
  print()

# ==============================================================================

# CASO DE USO: Resuma as vendas típicas

my_summary <- 
  sales |> 
  summarize(
    avg_items = mean(items),
    avg_spent = mean(spent)
  ) |> 
  print()

# ==============================================================================

# ARMADILHA: Não use summary() em vez de summarise()

my_summary <- 
  sales |> 
  summary(
    avg_items = mean(items),
    avg_spent = mean(spent)
  ) |> 
  print() # não é um tibble

# ==============================================================================

# CASO DE USO: Use mais de uma função de resumo

my_summary <- 
  sales |> 
  summarize(
    total_items = sum(items),
    total_spent = sum(spent),
    avg_items = mean(items),
    avg_spent = mean(spent)
  ) |> 
  print()

# ==============================================================================

# CASO DE USO: Usar funções de contagem

my_counts <- 
  sales |> 
  summarize(
    n_sales = n(),
    n_customers = n_distinct(customer),
    n_stores = n_distinct(store)
  ) |> 
  print()

Group Summarize

  • Também podemos resumir um tibble por grupo
    • Isto é como dobrar o tibble várias vezes
    • Especificamente, dobramos para uma linha por grupo
  • A sintaxe para resumir é idêntica
    • A única diferença é o tibble
    • Primeiro passamos por group_by()
    • Os pipelines tornam isso muito fácil

Group Summarize - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um conjunto de dados de exemplo

library(tidyverse)

sales <- 
  tibble(
    customer = c(1, 2, 3, 1, 3),
    store = c("A", "A", "A", "B", "B"),
    items = c(25, 20, 16, 10, 5),
    spent = c(685, 590, 392, 185, 123)
  ) |> 
  print()

# ==============================================================================

# LIÇÃO: Passamos um tibble por group_by para agrupá-lo

sales

sales |> group_by(store) # observe que o display diz "agrupado"

# ==============================================================================

# CASO DE USO: Podemos então resumir e obter estatísticas por grupo

sales |> 
  group_by(store) |> 
  summarize(
    customers = n_distinct(customer),
    items_sold = sum(items),
    total_sales = sum(spent),
    avg_items = mean(items),
    avg_spent = mean(spent)
  )

# ==============================================================================

# CONFIGURAÇÃO: Vamos obter um conjunto de dados maior e mais realista

# Extra pane > Packages tab > Install > nycflights13

library("nycflights13")

flights

# ==============================================================================

# CASO DE USO: Encontre a transportadora com os menores atrasos médios

flights |> 
  group_by(carrier) |> 
  summarize(m_delay = mean(dep_delay, na.rm = TRUE)) |> 
  arrange(m_delay)

# ==============================================================================

# LIÇÃO: Também podemos agrupar por múltiplas variáveis

# CASO DE USO: Vamos encontrar o dia do ano com mais voos

flights |> 
  group_by(month, day) |> 
  summarize(n_flights = n()) |> 
  arrange(desc(n_flights))

DataViz I

O que é um gráfico?

Uma visualização de dados que expressa os dados por meio de estética visual.

Por que expressamos dados em um gráfico?





Porque é importante visualizar dados antes de aplicar testes estatísticos inferenciais e descritivas.

Quarteto de Anscombe

Anscombe, F. J. (1973). Graphs in statistical analysis. The American Statistician, 27(1), 17–21.

Quarteto de Anscombe

Quarteto de Anscombe
x1 x2 x3 x4 y1 y2 y3 y4
1 10 10 10 8 8.04 9.14 7.46 6.58
2 8 8 8 8 6.95 8.14 6.77 5.76
3 13 13 13 8 7.58 8.74 12.74 7.71
4 9 9 9 8 8.81 8.77 7.11 8.84
5 11 11 11 8 8.33 9.26 7.81 8.47
6 14 14 14 8 9.96 8.10 8.84 7.04
7 6 6 6 8 7.24 6.13 6.08 5.25
8 4 4 4 19 4.26 3.10 5.39 12.50
9 12 12 12 8 10.84 9.13 8.15 5.56
10 7 7 7 8 4.82 7.26 6.42 7.91
11 5 5 5 8 5.68 4.74 5.73 6.89
Estatísticas Descritivas do Quarteto de Anscombe
Agrupadas por Conjunto

Características

1
N = 11

2
N = 11

3
N = 11

4
N = 11

x



    Média 9.00 9.00 9.00 9.00
    Desvio Padrão 3.32 3.32 3.32 3.32
y



    Média 7.50 7.50 7.50 7.50
    Desvio Padrão 2.03 2.03 2.03 2.03

Quarteto de Anscombe

Correlações do Quarteto de Anscombe
conjunto correlação
1 0.8164205
2 0.8162365
3 0.8162867
4 0.8165214

Observação: Correlação calculada conforme a correlação de Pearson

Quarteto de Anscombe

Modelo de Regressão Linear do Quarteto de Anscombe

Fórmula: y ~ x

Conjunto estimate std.error p.value.x conf.low conf.high r.squared adj.r.squared
1 0.5000909 0.1179055 0.002169629 0.2333701 0.7668117 0.6665425 0.6294916
2 0.5000000 0.1179637 0.002178816 0.2331475 0.7668525 0.6662420 0.6291578
3 0.4997273 0.1178777 0.002176305 0.2330695 0.7663851 0.6663240 0.6292489
4 0.4999091 0.1178189 0.002164602 0.2333841 0.7664341 0.6667073 0.6296747

Aplicando uma regressão linear teremos os mesmo \(p\)-valores, coeficientes, \(R^2\) e \(R^2\) ajustado para todos os quatro conjuntos.

The Datasaurus Dozen

O Datasaurus original foi criado por Alberto Cairo. As outras Dúzias é descrito no artigo “Same Stats, Different Graphs: Generating Datasets with VariedAppearance and Identical Statistics through Simulated Recoaling” de Justin Matejka e George Fitzmaurice.

The Datasaurus Dozen

Estatísticas Descritivas do Datasaurus Dozen
Agrupadas por Conjunto
Conjunto Média(X) Média(Y) Desv. Pad(X) Desv. Pad(Y) Correlação(X e Y)
away 54.26610 47.83472 16.76982 26.93974 -0.06412835
bullseye 54.26873 47.83082 16.76924 26.93573 -0.06858639
circle 54.26732 47.83772 16.76001 26.93004 -0.06834336
dino 54.26327 47.83225 16.76514 26.93540 -0.06447185
dots 54.26030 47.83983 16.76774 26.93019 -0.06034144
h_lines 54.26144 47.83025 16.76590 26.93988 -0.06171484
high_lines 54.26881 47.83545 16.76670 26.94000 -0.06850422
slant_down 54.26785 47.83590 16.76676 26.93610 -0.06897974
slant_up 54.26588 47.83150 16.76885 26.93861 -0.06860921
star 54.26734 47.83955 16.76896 26.93027 -0.06296110
v_lines 54.26993 47.83699 16.76996 26.93768 -0.06944557
wide_lines 54.26692 47.83160 16.77000 26.93790 -0.06657523
x_shape 54.26015 47.83972 16.76996 26.93000 -0.06558334

The Datasaurus Dozen

Porque usar gráficos

O quarteto de Anscombe e o Datasaurus Dozen são maneiras de ilustrar a importância de visualizações na análise de dados. Deve-se sempre olhar um conjunto de dados graficamente antes de começar qualquer análise, pois estes exemplos, ilustram contextos nos quais as propriedades estatísticas básicas para descrever conjuntos de dados são inadequadas, ou insuficiêntes.

Descrevendo gráficos

Alguns gráficos simples são fáceis de descrever e podem até ter nomes prontos.

Descrevendo gráficos

Uma gramática de gráficos nos ajudará a descrever gráficos mais complexidade.

The Grammar of Graphics

  • A gramática dos gráficos é um conjunto de regras para descrever e criar visualizações de dados
  • Para tornar nossos dados visuais (e, portanto, colocar nossos lobos occipitais altamente evoluídos para funcionar)…
    • Conectamos variáveis a qualidades visuais
    • Representamos observações como objetos visuais
  • Isso requer alguns elementos fundamentais
    • Primeiro aprenderemos sobre eles na aula
    • Em seguida, aplicaremos em R usando {ggplot2}

Aesthetic Mappings

Os gráficos exigem mapeamentos estéticos, que conectam variáveis a qualidades visuais.

Scales

Os gráficos requerem escalas, que conectam valores a estética.

Geoms

Os gráficos requerem objetos geométricos (geoms), que representam as observações.

O básico de ggplot2

  • O pacote ggplot2 faz parte do tidyverse
    • Não há necessidade de instalar ou carregar separadamente
    • Trabalha bem com tibbles & data wrangling
  • Ele implementa a gramática dos gráficos em R
    • O “gg” significa “gramática de gráficos”
    • Assim, precisaremos fornecer os elementos fundamentais
  • Criaremos um pseudo-pipeline de comandos
    • Entretanto, usaremos + em vez de %>%
    • Isso é porque o {ggplot2} é anterior ao pipe do R

ggplot2 - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um conjunto de dados de exemplo

library(tidyverse)

mpg

# ==============================================================================

# LIÇÃO: Primeiro, defina os dados para um tibble
p <- ggplot(data = mpg)
p

# ==============================================================================

# LIÇÃO: Em seguida, defina os mapeamentos estéticos com a função aes()

p <- ggplot(data = mpg, mapping = aes(x = displ, y = hwy))
p

# ==============================================================================

# DICA: Você pode usar aes() diretamente sem o argumento mapping

p <- ggplot(mpg, aes(x = displ, y = hwy))
p

# ==============================================================================

# LIÇÃO: Em seguida, defina as escalas posicionais

p <- ggplot(mpg, aes(x = displ, y = hwy)) +
  scale_x_continuous(
    name = "Engine Size (in liters)", 
    limits = c(1, 7), 
    breaks = 1:7
  ) +
  scale_y_continuous(
    name = "Highway Fuel Efficiency (in miles/gallon)",
    limits = c(10, 50),
    breaks = c(10, 20, 30, 40, 50)
  )
p

# ==============================================================================

# LIÇÃO: Por fim, adicione um ponto geométrico (geom)

p <- 
  ggplot(mpg, aes(x = displ, y = hwy)) + 
  scale_x_continuous(
    name = "Engine Size (in liters)", 
    limits = c(1, 7), 
    breaks = 1:7
  ) +
  scale_y_continuous(
    name = "Highway Fuel Efficiency (in miles/gallon)",
    limits = c(10, 50),
    breaks = c(10, 20, 30, 40, 50)
  ) +
  geom_point()

# ==============================================================================

# DICA: Se você deixar de fora as escalas, o R tentará adivinhar

p <- ggplot(mpg, aes(x = displ, y = hwy)) + geom_point()
p

# ==============================================================================

# LIÇÃO: Também podemos personalizar o geom com argumentos

p <- ggplot(mpg, aes(x = displ, y = hwy)) + 
  geom_point(color = "red", shape = "square", size = 2)
p

O básico sobre Camadas

  • ggplot2 usa uma gramática em camadas de gráficos
    • Permite empilhar geoms (formas geométricas)
  • Camadas adiciona muitas possibilidades
    • Podemos transmitir ideias mais complexas
    • Podemos aprender mais sobre nossos dados
  • Mas ainda podemos descrever esses gráficos
    • Apenas descreva cada camada por vez
    • E descreva a ordenação das camadas

Camadas ggplot2 - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um conjunto de dados de exemplo

library(tidyverse)

mpg

# ==============================================================================

# CASO DE USO: Adicionar uma geometria suave (geom_smooth), ou seja, linha de melhor ajuste. 

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point() +
  geom_smooth()

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point() +
  geom_smooth(method = "lm")

# ==============================================================================

# CASO DE USO: Adicionar uma linha geom (ou seja, pontos de conexão)

economics

ggplot(economics, aes(x = date, y = unemploy)) + 
  geom_point()

ggplot(economics, aes(x = date, y = unemploy)) + 
  geom_point() +
  geom_line(color = "orange", size = 1)

ggplot(economics, aes(x = date, y = unemploy)) + 
  geom_line(color = "orange", size = 1) +
  geom_point()

# ==============================================================================

# CASO DE USO: Adicionar linhas de referência geométricas

ggplot(economics, aes(x = date, y = unemploy)) + 
  geom_hline(yintercept = 0, color = "orange", size = 1) +
  geom_line(color = "blue", size = 1) +
  geom_point()

ggplot(economics, aes(x = date, y = unemploy)) + 
  geom_vline(xintercept = 7.5, color = "orange", size = 1) +
  geom_line(color = "blue", size = 1) +
  geom_point() 

ggplot(economics, aes(x = date, y = unemploy)) + 
  geom_abline(intercept = 4000, slope = 0.5, color = "orange", size = 1) +
  geom_line(color = "blue", size = 1) +
  geom_point() 

Trabalhando com cores

  • As escalas de cores são de dois tipos principais:
    • As escalas discretas têm cores separadas
      • Melhor com variáveis do tipo fator
    • As escalas Contínuas formam um gradiente
      • Melhor com variáveis numéricas
  • Existem duas maneiras de controlar a cor:
    • Você pode mapear a cor para uma variável
      • Assumirá valores diferentes
    • Você pode definir a cor para um valor
      • Ele assumirá um valor apenas

Cores - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um conjunto de dados de exemplo

library(tidyverse)

mpg

# ==============================================================================

# CASO DE USO: Escalas de cores contínuas funcionam bem com variáveis numéricas

ggplot(mpg, aes(x = hwy, y = cty, color = displ)) +
  geom_point(size = 4)

ggplot(mpg, aes(x = hwy, y = cty, color = displ)) +
  geom_point(size = 4) +
  scale_color_continuous(type = "viridis")

# ==============================================================================

# CASO DE USO: Use uma escala de cores discreta com variáveis categóricas

ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
  geom_point()

ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
  geom_point() +
  scale_color_discrete(
    name = "Drivetrain", 
    breaks = c("4", "f", "r"), 
    labels = c("Four Wheel", "Front Wheel", "Rear Wheel")
  )

# ==============================================================================

# ARMADILHA: Não se esqueça de definir variáveis categóricas como fatores

ggplot(mpg, aes(x = displ, y = hwy, color = cyl)) + 
  geom_point() # o R supõe que você quer uma escala contínua

ggplot(mpg, aes(x = displ, y = hwy, color = factor(cyl))) + 
  geom_point() + 
  scale_color_discrete(name = "Cylinders")

# ==============================================================================

# LIÇÃO: Defina a estética de cor de um geom para que ele sempre tenha essa cor

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(color = "red")

# ==============================================================================

# ARMADILHA: No entanto, faça isso dentro de geom() e não de aes()

ggplot(mpg, aes(x = displ, y = hwy, color = "blue")) + 
  geom_point()  # não intencional

# ==============================================================================

# LIÇÃO: Se você definir e mapear a cor, vai dar bom.

ggplot(mpg, aes(x = displ, y = hwy, color = drv)) + 
  geom_point(color = "blue") 

Temas

  • Temas controlam a aparência dos elementos não-dados
    • por exemplo, qual a espessura para desenhar as linhas de grade
    • por exemplo, onde posicionar a legenda
  • Temas completos alteram muitos elementos de uma só vez
    • Alguns estão incorporados ao ggplot2
    • Outros vêm em pacotes R
  • Elementos individuais também podem ser personalizados

Temas - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um gráfico de exemplo

library(tidyverse)

p <- 
  ggplot(mpg, aes(x = displ, y = hwy, color = drv)) + 
  geom_point() +
  labs(title = "Fuel Efficiency")
p

# ==============================================================================

# CASO DE USO: Aplicar um tema "completo"

p + theme_bw()

p + theme_classic()

p + theme_dark()

# ==============================================================================

# LIÇÃO: Controle mais preciso, podemos usar theme()

p + theme(legend.position = "top")

p + theme(plot.title = element_text(color = "purple", face = "bold"))

p + theme(panel.grid = element_blank())

# OBSERVAÇÃO: Há muitos elementos para aprender, então leia a documentação!

Exportando gráficos

  • Podemos precisar exportar gráficos do R
    • por exemplo, para um artigo, pôster ou apresentação
  • Este trabalho está sendo executado fantasticamente pela função ggsave()
    • Podemos criar muitos tipos de arquivos
    • Podemos personalizar o tamanho exato
  • Eu recomendo .png para a maioria dos propósitos diários
    • Para publicação, prefiro .pdf ou .svg
    • Eles mantêm a qualidade perfeita em qualquer zoom

Exportando gráficos - Prática

# CONFIGURAÇÃO: Precisaremos do tidyverse e de um gráfico de exemplo

library(tidyverse)

p <- ggplot(mpg, aes(x = displ, y = hwy)) + 
  geom_point() + geom_smooth() +
  labs(x = "Engine Displacement", y = "Highway MPG")
p

# ==============================================================================

# CASO DE USO: Salvar um objeto ggplot específico em um arquivo

ggsave(filename = "pfinal.png", plot = p)

# ==============================================================================

# LIÇÃO: Especifique o tamanho do arquivo a ser criado

ggsave(filename = "pfinal2.png", plot = p, 
       width = 6, height = 3, units = "in")

# ==============================================================================

# LIÇÃO: Basta alterar a extensão para criar um tipo de arquivo diferente

ggsave(filename = "pfinal2.pdf", plot = p, 
       width = 6, height = 3, units = "in")

# ==============================================================================

# ARMADILHA: Criar um arquivo muito grande pode resultar em texto pequeno

ggsave(filename = "p_poster.png", plot = p, 
       width = 12, height = 8, units = "in")

# ==============================================================================

# DICA: Você pode aumentar rapidamente o tamanho do texto usando base_size

p2 <- p + theme_grey(base_size = 24)

ggsave(filename = "p_poster2.png", plot = p2,
       width = 12, height = 8, units = "in")

Até o próximo encontro